package lightswitch.server.code.sqlhelper.statement.update;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import lightswitch.server.code.object.DataRow;
import lightswitch.server.code.object.Database;
import lightswitch.server.code.sqlhelper.ExpressionHelper;
import lightswitch.server.code.sqlhelper.expression.Expression;
import lightswitch.server.code.sqlhelper.expression.NormalTable;
import lightswitch.server.code.sqlhelper.statement.Statement;
import lightswitch.server.code.sqlhelper.statement.select.From;
import lightswitch.server.code.util.StringHelper;
import lightswitch.server.code.util.TypeOfData;

public class Update implements Statement {
	From from;
	Expression whereExpression;
	List<UpdateItem> itemsList;
	public Update(String statement) {
		parse(statement);
	}

	@Override
	public void parse(String statement) {
		// TODO Auto-generated method stub
		String mainTableString = "";
		String setValueString = "";
		String fromString = "";
		String whereString = "";
		String remainString ="";
		statement = StringHelper.NormalizeString(statement);
		
			Pattern p = Pattern.compile("((update[A-Za-z0-9 ,.\\*]+)set)(.*)");
			Matcher m = p.matcher(statement);
			if (m.find()) {
				mainTableString = m.group(1).substring(0, m.group(1).length()- "set".length());
				remainString = "set " +  m.group(3);
			
			}
		
			List<String> wordList=new ArrayList<>();
			// lay chuoi set..
			if(!remainString.equals(""))
			{
				
			
			wordList = StringHelper.SplitStringInEqualLevelKeepingToken(remainString);
			remainString="";
			boolean setfound = false;
			for(int i=0;i<wordList.size();i++)
			{
				if(setfound==false)
				{
					if(wordList.get(i).equals("from")||wordList.get(i).equals("where"))
					{
						setfound =true;
						remainString+=(" "+wordList.get(i));
					}
					else
					{
						setValueString+=(" "+wordList.get(i));
					}
				}
				else
				{
					remainString+=(" "+wordList.get(i));
				}
			}
			}
			else
			{
				//ko co set:
				//throw exception
				return;
			}
			
			//lay chuoi from
			if(!remainString.equals(""))
			{
				
			wordList.clear();
			wordList = StringHelper.SplitStringInEqualLevelKeepingToken(remainString);
			remainString="";
			boolean fromfound = false;
			for(int i=0;i<wordList.size();i++)
			{
				if(fromfound==false)
				{
					if(wordList.get(i).equals("where"))
					{
						fromfound =true;
						remainString+=(" "+wordList.get(i));
					}
					else
					{
						fromString+=(" "+wordList.get(i));
					}
				}
				else
				{
					remainString+=(" "+wordList.get(i));
				}
			}
			}
		
			whereString = remainString;
//		
//			String mainTableString = "";
//			String setValueString = "";
//			String fromString = "";
//			String  = "";
//			
		
			if(mainTableString.contains("update"))
			{
				mainTableString = mainTableString.substring("update ".length());
			}
			if(setValueString.contains("set"))
			{
				setValueString = setValueString.substring("set  ".length());
			}
			if(fromString.contains("from"))
			{
				fromString = fromString.substring("from ".length());
			}
			if(whereString.contains("where"))
			{
				whereString = whereString.substring("where ".length());
			}
			
		String frString = "from "+ mainTableString;
		if(!fromString.equals(""))
		{
			frString = frString + ", " + fromString;
		}
	
		from  =new From(frString,null);
		whereExpression = ExpressionHelper.parseExpression(whereString, from);
		itemsList = new ArrayList<>();
		setValueString= StringHelper.NormalizeString(setValueString);
		String[] str = setValueString.split(",");
		for(int i=0;i<str.length;i++)
		{
			String[] spl = StringHelper.NormalizeString(str[i]).split("=");
			if(spl.length==2)
			{
				UpdateItem item =  new UpdateItem(str[i], from);
				itemsList.add(item);
			}
			else
			{
				//throw exception
				return;
			}
		}
	

	}
	public int execute() {
		List<From> list = new ArrayList<>();
		list.add(from);
        int numOfRows = 0;
        for (int i = 0; i < from._tableList.size(); i++) {
            from._tableList.get(i).InitTable();
        }

        NormalTable mainTable = (NormalTable) from._tableList.get(0);

        NormalTable _temp = null;
        if (from._tableList.size() > 0) {
            _temp = (NormalTable) from._tableList.get(0).getAsNormalTable();
        } else
            return -1;

        for (int i = 1; i < from._tableList.size(); i++) {
            _temp = _temp.MultiWith((NormalTable) from._tableList.get(i), from._joinExpression.get(i));

        }

        for (int i = 0; i < _temp.dataRowList.size(); i++) {

            if (((boolean) whereExpression.GetValue((_temp.dataRowList.get(i)),list)) == false) {
                _temp.dataRowList.remove(i);
                i--;
            }

        }

      
        for (int i = mainTable.propertyList.size(); i < _temp.propertyList.size(); i++) {
            _temp.RemoveColumn(i);
            i--;

        }

        for (int i = 0; i < mainTable.dataRowList.size(); i++) {
            for (int j = 0; j < _temp.dataRowList.size(); j++) {
                if (mainTable.dataRowList.get(i).isLike(_temp.dataRowList.get(j))) {
                	
                    DataRow tempUpdate = new DataRow(mainTable.dataRowList.get(i));
                    for (int k = 0; k < itemsList.size(); k++) {
                    	Object value = itemsList.get(k).getValue(tempUpdate);
                    	
                    	
                        String acceptType = mainTable.dataRowList.get(i).getEntryDataType(itemsList.get(k).name);
                        if (acceptType.equals(TypeOfData.FLOAT) || acceptType.equals(TypeOfData.INT))
                            acceptType = TypeOfData.FLOAT;
                        if (acceptType.equals(itemsList.get(k).dataType)
                                || (itemsList.get(k).equals("null") && itemsList.get(k).dataType
                                        .equals(TypeOfData.CHAR))) {
                            tempUpdate.updateEntry(itemsList.get(k).name, value.toString());
                        } 

                    }
                    if (Database.isCanUpdate(mainTable.name, mainTable.dataRowList.get(i), tempUpdate)){
                        if (Database.getLoadedTable(mainTable.name).editDataRoẉ̣̣̣̣̣̣̣( mainTable.dataRowList.get(i), tempUpdate))
                            numOfRows++;
                    }
                    
                    break;
                }
            }
        }
        return numOfRows;
    }
}
